/**
 * @file DataBase.h
 * @Synopsis
 * @author Mingyu Wu
 * @version 1.0.0
 * @date 2024-04-20
 */

#ifndef _DATA_BASE_H_
#define _DATA_BASE_H_

#include "../Util.h"
#include "Configuration.h"

#include <algorithm>
#include <chrono>
#include <ctime>
#include <iterator>
#include <memory>
#include <string>
#include <strings.h>
#include <sw/redis++/connection.h>
#include <sw/redis++/errors.h>
#include <sw/redis++/redis++.h>
#include <sw/redis++/redis_cluster.h>
#include <thread>
#include <unistd.h>
#include <unordered_map>
#include <vector>
#include <zlog.h>

using namespace sw::redis;

class DataBase {
  public:
    DataBase();

    virtual ~DataBase();
    int Init();

    /**
     * @Synopsis 查询redis集群在线情况
     *
     * @return true: 在线, false:不在线
     */
    bool IsServerOnline();

    // NOTE:: TransportationLayer Methode
    /**
     * @Synopsis  上传 hash tab 到redis
     *
     * @Param hashKey key
     *
     *@Param data  hash table
     *
     * @return 成功返回 ErrorInfo::OK,  失败返回错误码
     */
    int UploadHandler(std::string hashKey,
                      const std::unordered_map<std::string, std::string> &data);

    int StreamRecv(std::unordered_map<std::string, std::string> &controlData);

    // NOTE: ApplicationLayer Methode
    /**
     * @Synopsis 数据查询
     *
     * @Param hashKey
     * @Param data
     *
     * @return
     */
    int QueryData(std::string                                   hashKey,
                  std::unordered_map<std::string, std::string> &data);

    int
    StreamSend(std::string                                       streamKey,
               std::vector<std::pair<std::string, std::string>> &controlData);

    void GetID();

  public:
    static int recvStreamCount;

  private:
    int ConnectCluster();

    int CreateConnection(ConnectionOptions option);

    void CreatePingCommand(std::string &command, std::string host, int port);

    void CreateClusterCommand(std::string &command, std::string host, int port);

    int SendCommand(std::string command);

    int ConnectNode(int index);

    int CheckClusterStatus(int index);

    // TODO : stream启动之前 先清空队列消息
    void CleanStream();

  private:
    // Redis connection info
    std::vector<ConnectionOptions> connection_options;
    // ConnectionOptions     connection_options[7];
    ConnectionPoolOptions pool_options;

    static std::unique_ptr<RedisCluster> cluster;
    static bool                          online;

    std::string streamID;              // stream 时间戳
    const int   overtime = 10;
    const int STREAM_ID_OFFSET = 5000; // ms,为了防止控制器之间的时间不同步
};

#endif // !_DATA_BASE_H_
